from argparse import ArgumentParser
import pygame
from pygame.locals import *
from time import *
from Board2DRender import Board2DRenderer
from Board import Board
   
parser = ArgumentParser()

parser.add_argument('-v_cells',type=int, default=250, help='number of vertical cells')
parser.add_argument('-h_cells',type=int, default=250, help='number of horizontal cells')
parser.add_argument('-resolution', nargs=2,type=int, default=(1000,1000), help='screen resolution')
parser.add_argument('-opencl', action='store_true', help='run with openCL')
parser.add_argument('-steps', default=0, type=int, help='number of steps, infinite by default(steps = 0)')
parser.add_argument('-ntraj', default=1, type=int, help='number of trajectories')
parser.add_argument('-stasis_stop', action='store_true', help='stop the run the system has reach stasis')
parser.add_argument('-off_graphics', action='store_true', help="don't render, run in batch mode")
parser.add_argument('-check_stasis', default=100, type=int,help='check for stasis every nth step')
parser.add_argument('-init_alive', default=0.5, type=float,help='ratio of randomly alive cells when initializing the board')
parser.add_argument('-rule', nargs=3,type=int, default=(2,3,3), help='update rule, the first numbers are lonelyness, reproduction and overcrowded numbers. default is 2 3 3')




args = parser.parse_args()

pygame.init()


screen = None if args.off_graphics else pygame.display.set_mode(args.resolution, 0)
#initialize a board
start = time()
if args.opencl:
  import pyopencl as cl
  from BoardOpenCL import BoardOpenCL
  ctx = cl.create_some_context(0)
  mf = cl.mem_flags
  queue = cl.CommandQueue(ctx)
  board = BoardOpenCL(args.v_cells, args.h_cells, ctx, queue, mf)
else:
  board = Board(args.v_cells, args.h_cells, rule=args.rule, init_alive=args.init_alive)

renderer = Board2DRenderer()
for ntraj in range(1, args.ntraj + 1):
  print '\n-------------- Trajectory ', ntraj, '--------------'
  board.initialize()
  if not args.off_graphics:
    screen.lock()
    renderer.render( screen, board )
    screen.unlock()
  iteration = 1
  mainloop = True
  stasis_step_num = 0
  while mainloop and iteration != args.steps:
    for event in pygame.event.get():
      if event.type == QUIT or args.steps == iteration:
        mainloop = False
    
    board.step()
    if not args.off_graphics:
      screen.lock()
      renderer.render( screen, board )
      screen.unlock()
  
    if not args.off_graphics:
      pygame.display.update()
  
    if not iteration % args.check_stasis: 
        if board.check_stasis(renderer, screen, board, pygame.display.update, render_off=args.off_graphics):
          if args.stasis_stop:
            print 'system is stasis, stopping the program'
            mainloop = False
          if stasis_step_num == 0:
            stasis_step_num = iteration 

    iteration += 1


  print "number of iterations: ", iteration
  print "stasis detected at iteration: ", stasis_step_num
  print "iter/sec: ", iteration/(time() - start)
